<!--
  Copyright JS Foundation and other contributors, http://js.foundation

  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

  http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
-->

<script type="text/html" data-template-name="switch">
    <div class="form-row">
        <label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
        <input type="text" id="node-input-name" data-i18n="[placeholder]common.label.name">
    </div>
    <div class="form-row">
        <label for="node-input-property"><i class="fa fa-ellipsis-h"></i> <span
                data-i18n="switch.label.property"></span></label>
        <input type="text" id="node-input-property" style="width: 70%"/>
        <input type="hidden" id="node-input-outputs"/>
    </div>
    <div class="form-row node-input-rule-container-row">
        <ol id="node-input-rule-container"></ol>
    </div>
    <div class="form-row">
        <select id="node-input-checkall" style="width:100%; margin-right:5px;">
            <option value="true" data-i18n="switch.checkall"></option>
            <option value="false" data-i18n="switch.stopfirst"></option>
        </select>
    </div>
<!--    <div class="form-row">-->
<!--        <input type="checkbox" id="node-input-repair" style="display: inline-block; width: auto; vertical-align: top;">-->
<!--        <label style="width: auto;" for="node-input-repair"><span-->
<!--                data-i18n="switch.label.repair"></span></label></input>-->
<!--    </div>-->
</script>

<script type="text/javascript">
    (function () {
        var operators = [
            {v: "eq", t: "==", kind: 'V'},
            {v: "neq", t: "!=", kind: 'V'},
            {v: "lt", t: "<", kind: 'V'},
            {v: "lte", t: "<=", kind: 'V'},
            {v: "gt", t: ">", kind: 'V'},
            {v: "gte", t: ">=", kind: 'V'},
            {v: "hask", t: "switch.rules.hask", kind: 'V'},
            // {v: "btwn", t: "switch.rules.btwn", kind: 'V'},
            {v: "cont", t: "switch.rules.cont", kind: 'V'},
            {v: "regex", t: "switch.rules.regex", kind: 'V'},
            {v: "true", t: "switch.rules.true", kind: 'V'},
            {v: "false", t: "switch.rules.false", kind: 'V'},
            {v: "null", t: "switch.rules.null", kind: 'V'},
            {v: "nnull", t: "switch.rules.nnull", kind: 'V'},
            {v: "istype", t: "switch.rules.istype", kind: 'V'},
            {v: "empty", t: "switch.rules.empty", kind: 'V'},
            {v: "nempty", t: "switch.rules.nempty", kind: 'V'},
            {v: "jsonata_exp", t: "switch.rules.exp", kind: 'O'},
            {v: "else", t: "switch.rules.else", kind: 'O'}
        ];

        function clipValueLength(v) {
            if (v.length > 15) {
                return v.substring(0, 15) + "...";
            }
            return v;
        }

        function prop2name(key) {
            var result = RED.utils.parseContextKey(key);
            return result.key;
        }

        function getValueLabel(t, v) {
            if (t === 'str') {
                return '"' + clipValueLength(v) + '"';
            } else if (t === 'msg') {
                return t + "." + clipValueLength(v);
            } else if (t === 'flow' || t === 'global') {
                return t + "." + clipValueLength(prop2name(v));
            }
            return clipValueLength(v);
        }

        RED.nodes.registerType('switch', {
            color: "#E2D96E",
            category: 'common',
            name: "路由",
            defaults: {
                name: {value: ""},
                property: {value: "data", required: true, validate: RED.validators.typedInput("propertyType")},
                propertyType: {value: "jsonata"},
                rules: {value: [{t: "eq", v: "", vt: "str"}]},
                checkall: {value: "true", required: true},
                // repair: {value: false},
                outputs: {value: 1}
            },
            inputs: 1,
            outputs: 1,
            outputLabels: function (index) {
                var rule = this.rules[index];
                var label = "";
                if (rule) {
                    for (var i = 0; i < operators.length; i++) {
                        if (operators[i].v === rule.t) {
                            label = /^switch/.test(operators[i].t) ? this._(operators[i].t) : operators[i].t;
                            break;
                        }
                    }
                    if ((rule.t === 'btwn') || (rule.t === 'index')) {
                        label += " " + getValueLabel(rule.vt, rule.v) + " & " + getValueLabel(rule.v2t, rule.v2);
                    } else if (rule.t !== 'true' && rule.t !== 'false' && rule.t !== 'null' && rule.t !== 'nnull' && rule.t !== 'empty' && rule.t !== 'nempty' && rule.t !== 'else') {
                        label += " " + getValueLabel(rule.vt, rule.v);
                    }
                    return label;
                }
            },
            icon: "switch.svg",
            label: function () {
                return this.name || "路由";
            },
            labelStyle: function () {
                return this.name ? "node_label_italic" : "";
            },
            oneditprepare: function () {
                var node = this;

                var previousValueType = {value: "prev", label: this._("switch.previous"), hasValue: false};

                $("#node-input-property").typedInput({default: this.propertyType || 'jsonata', types: ['jsonata','str','num','env']});
                var outputCount = $("#node-input-outputs").val("{}");

                var andLabel = this._("switch.and");
                var caseLabel = this._("switch.ignorecase");

                function resizeRule(rule) {
                    var newWidth = rule.width();
                    var selectField = rule.find("select");
                    var type = selectField.val() || "";
                    var valueField = rule.find(".node-input-rule-value");
                    var typeField = rule.find(".node-input-rule-type-value");
                    var numField = rule.find(".node-input-rule-num-value");
                    var expField = rule.find(".node-input-rule-exp-value");
                    var keyField = rule.find(".node-input-rule-key-value");
                    var btwnField1 = rule.find(".node-input-rule-btwn-value");
                    var btwnField2 = rule.find(".node-input-rule-btwn-value2");
                    var selectWidth;
                    if (type.length < 4) {
                        selectWidth = 60;
                    } else if (type === "regex") {
                        selectWidth = 147;
                    } else {
                        selectWidth = 120;
                    }
                    selectField.width(selectWidth);
                    if ((type === "btwn") || (type === "index")) {
                        btwnField1.typedInput("width", (newWidth - selectWidth - 70));
                        btwnField2.typedInput("width", (newWidth - selectWidth - 70));
                    } else if ((type === "head") || (type === "tail")) {
                        numField.typedInput("width", (newWidth - selectWidth - 70));
                    } else if (type === "jsonata_exp") {
                        expField.typedInput("width", (newWidth - selectWidth - 70));
                    } else if (type === "istype") {
                        typeField.typedInput("width", (newWidth - selectWidth - 70));
                    } else {
                        if (type === "true" || type === "false" || type === "null" || type === "nnull" || type === "empty" || type === "nempty" || type === "else") {
                            // valueField.hide();
                        } else {
                            valueField.typedInput("width", (newWidth - selectWidth - 70));
                        }
                    }
                }

                $("#node-input-rule-container").css('min-height', '150px').css('min-width', '450px').editableList({
                    addItem: function (container, i, opt) {
                        if (!opt.hasOwnProperty('r')) {
                            opt.r = {};
                        }
                        var rule = opt.r;
                        if (!rule.hasOwnProperty('t')) {
                            rule.t = 'eq';
                        }
                        if (!opt.hasOwnProperty('i')) {
                            opt._i = Math.floor((0x99999 - 0x10000) * Math.random()).toString();
                        }
                        container.css({
                            overflow: 'hidden',
                            whiteSpace: 'nowrap'
                        });
                        var row = $('<div/>').appendTo(container);
                        var row2 = $('<div/>', {style: "padding-top: 5px; padding-left: 175px;"}).appendTo(container);
                        var row3 = $('<div/>', {style: "padding-top: 5px; padding-left: 102px;"}).appendTo(container);
                        var selectField = $('<select/>', {style: "width:120px; margin-left: 5px; text-align: center;"}).appendTo(row);
                        var group0 = $('<optgroup/>', {label: "值判断"}).appendTo(selectField);
                        for (var d in operators) {
                            if (operators[d].kind === 'V') {
                                group0.append($("<option></option>").val(operators[d].v).text(/^switch/.test(operators[d].t) ? node._(operators[d].t) : operators[d].t));
                            }
                        }
                        var group1 = $('<optgroup/>', {label: "其他"}).appendTo(selectField);
                        for (var d in operators) {
                            if (operators[d].kind === 'S') {
                                group1.append($("<option></option>").val(operators[d].v).text(/^switch/.test(operators[d].t) ? node._(operators[d].t) : operators[d].t));
                            }
                        }
                        for (var d in operators) {
                            if (operators[d].kind === 'O') {
                                selectField.append($("<option></option>").val(operators[d].v).text(/^switch/.test(operators[d].t) ? node._(operators[d].t) : operators[d].t));
                            }
                        }

                        function createValueField() {
                            return $('<input/>', {
                                class: "node-input-rule-value",
                                type: "text",
                                style: "margin-left: 5px;"
                            })
                                .appendTo(row)
                                .typedInput({
                                    default: 'str',
                                    types: ['str', 'num', 'jsonata', 'env']
                                });
                        }

                        function createNumValueField() {
                            return $('<input/>', {
                                class: "node-input-rule-num-value",
                                type: "text",
                                style: "margin-left: 5px;"
                            }).appendTo(row).typedInput({
                                default: 'num',
                                types: ['num', 'jsonata', 'env']
                            });
                        }

                        function createExpValueField() {
                            return $('<input/>', {
                                class: "node-input-rule-exp-value",
                                type: "text",
                                style: "margin-left: 5px;"
                            }).appendTo(row).typedInput({default: 'jsonata', types: ['jsonata']});
                        }

                        function createBtwnValueField() {
                            return $('<input/>', {
                                class: "node-input-rule-btwn-value",
                                type: "text",
                                style: "margin-left: 5px;"
                            }).appendTo(row).typedInput({
                                default: 'num',
                                types: [ 'str', 'num', 'jsonata', 'env']
                            });
                        }

                        function createBtwnAndLabel() {
                            return $('<span/>', {class: "node-input-rule-btwn-label"}).text(" " + andLabel + " ").appendTo(row3);
                        }

                        function createBtwnValue2Field() {
                            return $('<input/>', {
                                class: "node-input-rule-btwn-value2",
                                type: "text",
                                style: "margin-left:2px;"
                            }).appendTo(row3).typedInput({
                                default: 'num',
                                types: [ 'str', 'num', 'jsonata', 'env']
                            });
                        }

                        function createTypeValueField() {
                            return $('<input/>', {
                                class: "node-input-rule-type-value",
                                type: "text",
                                style: "margin-left: 5px;"
                            }).appendTo(row).typedInput({
                                default: 'string', types: [
                                    {
                                        value: "string",
                                        label: RED._("common.type.string"),
                                        hasValue: false,
                                        icon: "red/images/typedInput/az.png"
                                    },
                                    {
                                        value: "number",
                                        label: RED._("common.type.number"),
                                        hasValue: false,
                                        icon: "red/images/typedInput/09.png"
                                    },
                                    {
                                        value: "boolean",
                                        label: RED._("common.type.boolean"),
                                        hasValue: false,
                                        icon: "red/images/typedInput/bool.png"
                                    },
                                    {
                                        value: "array",
                                        label: RED._("common.type.array"),
                                        hasValue: false,
                                        icon: "red/images/typedInput/json.png"
                                    },
                                    {
                                        value: "buffer",
                                        label: RED._("common.type.buffer"),
                                        hasValue: false,
                                        icon: "red/images/typedInput/bin.png"
                                    },
                                    {
                                        value: "object",
                                        label: RED._("common.type.object"),
                                        hasValue: false,
                                        icon: "red/images/typedInput/json.png"
                                    },
                                    {
                                        value: "json",
                                        label: RED._("common.type.jsonString"),
                                        hasValue: false,
                                        icon: "red/images/typedInput/json.png"
                                    },
                                    {value: "undefined", label: RED._("common.type.undefined"), hasValue: false},
                                    {value: "null", label: RED._("common.type.null"), hasValue: false}
                                ]
                            });
                        }

                        var valueField = null;
                        var numValueField = null;
                        var expValueField = null;
                        var btwnAndLabel = null;
                        var btwnValueField = null;
                        var btwnValue2Field = null;
                        var typeValueField = null;

                        var finalspan = $('<span/>', {style: "float: right;margin-top: 6px;"}).appendTo(row);
                        finalspan.append(' &#8594; <span class="node-input-rule-index">' + (i + 1) + '</span> ');
                        var caseSensitive = $('<input/>', {
                            id: "node-input-rule-case-" + i,
                            class: "node-input-rule-case",
                            type: "checkbox",
                            style: "width:auto;vertical-align:top"
                        }).appendTo(row2);
                        $('<label/>', {
                            for: "node-input-rule-case-" + i,
                            style: "margin-left: 3px;"
                        }).text(caseLabel).appendTo(row2);
                        selectField.on("change", function () {
                            var type = selectField.val();
                            if (valueField) {
                                valueField.typedInput('hide');
                            }
                            if (expValueField) {
                                expValueField.typedInput('hide');
                            }
                            if (numValueField) {
                                numValueField.typedInput('hide');
                            }
                            if (typeValueField) {
                                typeValueField.typedInput('hide');
                            }
                            if (btwnValueField) {
                                btwnValueField.typedInput('hide');
                            }
                            if (btwnValue2Field) {
                                btwnValue2Field.typedInput('hide');
                            }

                            if ((type === "btwn") || (type === "index")) {
                                if (!btwnValueField) {
                                    btwnValueField = createBtwnValueField();
                                }
                                btwnValueField.typedInput('show');
                            } else if ((type === "head") || (type === "tail")) {
                                if (!numValueField) {
                                    numValueField = createNumValueField();
                                }
                                numValueField.typedInput('show');
                            } else if (type === "jsonata_exp") {
                                if (!expValueField) {
                                    expValueField = createExpValueField();
                                }
                                expValueField.typedInput('show');
                            } else if (type === "istype") {
                                if (!typeValueField) {
                                    typeValueField = createTypeValueField();
                                }
                                typeValueField.typedInput('show');
                            } else if (!(type === "true" || type === "false" || type === "null" || type === "nnull" || type === "empty" || type === "nempty" || type === "else")) {
                                if (!valueField) {
                                    valueField = createValueField();
                                }
                                valueField.typedInput('show');
                            }
                            if (type === "regex") {
                                row2.show();
                                row3.hide();
                            } else if ((type === "btwn") || (type === "index")) {
                                row2.hide();
                                row3.show();
                                if (!btwnValue2Field) {
                                    btwnValue2Field = createBtwnValue2Field();
                                }
                                btwnValue2Field.typedInput('show');
                            } else {
                                row2.hide();
                                row3.hide();
                            }
                            resizeRule(container);

                        });
                        selectField.val(rule.t);
                        if ((rule.t == "btwn") || (rule.t == "index")) {
                            if (!btwnValueField) {
                                btwnValueField = createBtwnValueField();
                            }
                            btwnValueField.typedInput('value', rule.v);
                            btwnValueField.typedInput('type', rule.vt || 'num');

                            if (!btwnValue2Field) {
                                btwnValue2Field = createBtwnValue2Field();
                            }
                            btwnValue2Field.typedInput('value', rule.v2);
                            btwnValue2Field.typedInput('type', rule.v2t || 'num');
                        } else if ((rule.t === "head") || (rule.t === "tail")) {
                            if (!numValueField) {
                                numValueField = createNumValueField();
                            }
                            numValueField.typedInput('value', rule.v);
                            numValueField.typedInput('type', rule.vt || 'num');
                        } else if (rule.t === "istype") {
                            if (!typeValueField) {
                                typeValueField = createTypeValueField();
                            }
                            typeValueField.typedInput('value', rule.vt);
                            typeValueField.typedInput('type', rule.vt);
                        } else if (rule.t === "jsonata_exp") {
                            if (!expValueField) {
                                expValueField = createExpValueField();
                            }
                            expValueField.typedInput('value', rule.v);
                            expValueField.typedInput('type', rule.vt || 'jsonata');
                        } else if (typeof rule.v != "undefined") {
                            if (!valueField) {
                                valueField = createValueField();
                            }
                            valueField.typedInput('value', rule.v);
                            valueField.typedInput('type', rule.vt || 'str');
                        }
                        if (rule.case) {
                            caseSensitive.prop('checked', true);
                        } else {
                            caseSensitive.prop('checked', false);
                        }
                        selectField.change();

                        var currentOutputs = JSON.parse(outputCount.val() || "{}");
                        currentOutputs[opt.hasOwnProperty('i') ? opt.i : opt._i] = i;
                        outputCount.val(JSON.stringify(currentOutputs));
                    },
                    removeItem: function (opt) {
                        var currentOutputs = JSON.parse(outputCount.val() || "{}");
                        if (opt.hasOwnProperty('i')) {
                            currentOutputs[opt.i] = -1;
                        } else {
                            delete currentOutputs[opt._i];
                        }
                        var rules = $("#node-input-rule-container").editableList('items');
                        rules.each(function (i) {
                            $(this).find(".node-input-rule-index").html(i + 1);
                            var data = $(this).data('data');
                            currentOutputs[data.hasOwnProperty('i') ? data.i : data._i] = i;
                        });
                        outputCount.val(JSON.stringify(currentOutputs));
                    },
                    resizeItem: resizeRule,
                    sortItems: function (rules) {
                        var currentOutputs = JSON.parse(outputCount.val() || "{}");
                        var rules = $("#node-input-rule-container").editableList('items');
                        rules.each(function (i) {
                            $(this).find(".node-input-rule-index").html(i + 1);
                            var data = $(this).data('data');
                            currentOutputs[data.hasOwnProperty('i') ? data.i : data._i] = i;
                        });
                        outputCount.val(JSON.stringify(currentOutputs));
                    },
                    sortable: true,
                    removable: true
                });

                for (var i = 0; i < this.rules.length; i++) {
                    var rule = this.rules[i];
                    $("#node-input-rule-container").editableList('addItem', {r: rule, i: i});
                }
            },
            oneditsave: function () {
                var rules = $("#node-input-rule-container").editableList('items');
                var node = this;
                node.rules = [];
                rules.each(function (i) {
                    var rule = $(this);
                    var type = rule.find("select").val();
                    var r = {t: type};
                    if (!(type === "true" || type === "false" || type === "null" || type === "nnull" || type === "empty" || type === "nempty" || type === "else")) {
                        if ((type === "btwn") || (type === "index")) {
                            r.v = rule.find(".node-input-rule-btwn-value").typedInput('value');
                            r.vt = rule.find(".node-input-rule-btwn-value").typedInput('type');
                            r.v2 = rule.find(".node-input-rule-btwn-value2").typedInput('value');
                            r.v2t = rule.find(".node-input-rule-btwn-value2").typedInput('type');
                        } else if ((type === "head") || (type === "tail")) {
                            r.v = rule.find(".node-input-rule-num-value").typedInput('value');
                            r.vt = rule.find(".node-input-rule-num-value").typedInput('type');
                        } else if (type === "istype") {
                            r.v = rule.find(".node-input-rule-type-value").typedInput('type');
                            r.vt = rule.find(".node-input-rule-type-value").typedInput('type');
                        } else if (type === "jsonata_exp") {
                            r.v = rule.find(".node-input-rule-exp-value").typedInput('value');
                            r.vt = rule.find(".node-input-rule-exp-value").typedInput('type');
                        } else {
                            r.v = rule.find(".node-input-rule-value").typedInput('value');
                            r.vt = rule.find(".node-input-rule-value").typedInput('type');
                        }
                        if (type === "regex") {
                            r.case = rule.find(".node-input-rule-case").prop("checked");
                        }
                    }
                    node.rules.push(r);
                });
                this.propertyType = $("#node-input-property").typedInput('type');
            },
            oneditresize: function (size) {
                var rows = $("#dialog-form>div:not(.node-input-rule-container-row)");
                var height = size.height;
                for (var i = 0; i < rows.length; i++) {
                    height -= $(rows[i]).outerHeight(true);
                }
                var editorRow = $("#dialog-form>div.node-input-rule-container-row");
                height -= (parseInt(editorRow.css("marginTop")) + parseInt(editorRow.css("marginBottom")));
                height += 16;
                $("#node-input-rule-container").editableList('height', height);
            }
        });
    })();
</script>
